<?php
/**
 * +-------------------------------------------------------------
 * |Caption:
 * +-------------------------------------------------------------
 * |Author: Lenny
 * +-------------------------------------------------------------
 * |Email:  1685964109@qq.com
 * +-------------------------------------------------------------
 * |Date:   2024/8/5 下午2:14
 * +-------------------------------------------------------------
 */

namespace app\common\service;

use app\common\enum\order\OrderStatus;
use app\common\exception\BaseException;

//use app\common\Jobs\OrderCancellationJob;
//use app\store\model\StoreUserOrder;
use think\facade\Queue;

class WeChatPayService
{

    protected $model;

    /**
     * 微信支付
     * JSAPI 官方文档：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
     * 文档 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_4.shtml
     */
    public static function unifiedorder($orderInfo, $openid, $description): array
    {
        $app      = \app\common\service\EasyWechatService::getPayApp();
        $account  = $app->getMerchant();
        $config   = $app->getConfig();
        $api      = $app->getClient();
        $utils    = $app->getUtils();
        $data     = [
                "mchid"        => (string)$account->getMerchantId(),
                "out_trade_no" => (string)$orderInfo->order_no,
                'attach'       => json_encode([
                                                      'order_type' => $orderInfo->order_type,
                                                      'pay_source' => $orderInfo->platform
                                              ], JSON_THROW_ON_ERROR),
                "appid"        => (string)$config->get('app_id'),
                "description"  => (string)$description,
                "notify_url"   => \app\common\service\base_url() . 'api/notify',
                "amount"       => [
                        "total"    => (int)$orderInfo->order_amount * 100,
                        "currency" => "CNY"
                ],
                "payer"        => [
                        "openid" => $openid
                ]
        ];
        $url      = "v3/pay/transactions/jsapi";
        $response = $api->postJson($url, $data);
        $result   = $response->toArray(false);
        if (!isset($result['prepay_id'])) {
            throw new BaseException(['message' => '微信支付失败！' . $result['message']]);
        }
        $appId    = (string)$config->get('app_id');
        $signType = 'RSA';                                                                              // 默认RSA，v2要传MD5
        Queue::later(60 * 30, OrderCancellationJob::class, $orderInfo, 'order_cancellation_job_queue'); // 超时30分钟自动取消订单
        return $utils->buildMiniAppConfig($result['prepay_id'], $appId, $signType);                     // 返回数组
    }


    public function notify_test($no)
    {
        // 建议是拿订单号调用微信支付查询接口，以查询到的订单状态为准
        $weChatOrder = $this->checkOrder($no);
        // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
        //        $order = StoreUserOrder::where('order_no', $no)->find();
        // 如果订单不存在 或者 订单已经支付过了
        //        if(!$order || $order->status === OrderStatus::PAID || $weChatOrder['trade_state'] === 'SUCCESS') {
        //            return true;     // 告诉微信，我已经处理完了，订单没找到，别再通知我了
        //        }
        //        $order->status = OrderStatus::PAID;
        //        $order->save();
        // 触发支付成功事件
        //        event('OrderPaySuccess', $order);
    }

    /**
     * 微信支付通知
     * 文档 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
     */
    public function notify()
    {
        trace('这是一条支付回调日志信息', 'notice');
        $app    = \app\common\service\EasyWechatService::getPayApp();
        $server = $app->getServer();
        $server->handlePaid(function ($message, \Closure $next)
        {
            trace($message, 'notice');
            // $message->out_trade_no 获取商户订单号
            // $message->payer['openid'] 获取支付者 openid
            // 🚨🚨🚨 注意：推送信息不一定靠谱哈，请务必验证
            // 建议是拿订单号调用微信支付查询接口，以查询到的订单状态为准
            $weChatOrder = $this->checkOrder($message->out_trade_no);
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            $order = StoreUserOrder::where('order_no', $message['out_trade_no'])->find();
            if (!$order || $order->status === 2 || $weChatOrder['trade_state'] === 'SUCCESS') { // 如果订单不存在 或者 订单已经支付过了
                return true;                                                                    // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }
            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    // 支付成功，更新订单状态
                    $order->status = OrderStatus::PAID;
                } elseif ($message['result_code'] === 'FAIL') {
                    // 用户支付失败
                    $order->status = OrderStatus::PAY_FAIL;
                }
            }
            $order->save();
            // 触发支付成功事件
            event('OrderPaySuccess', $order);
            return $next($message);
        });

        // 默认返回 ['code' => 'SUCCESS', 'message' => '成功']
        return $server->serve();
    }

    /**
     * 查询微信订单订单
     */
    public function checkOrder($out_trade_no = '', $transaction_id = '')
    {
        // 创建微信支付对象
        $app  = \app\common\service\EasyWechatService::getPayApp();
        $api  = $app->getClient();
        $data = [
                'query' => [
                        'mchid' => $app->getMerchant()->getMerchantId()
                ]
        ];
        // 交易订单号查询订单
        if ($out_trade_no) {
            $url = "v3/pay/transactions/out-trade-no/{$out_trade_no}";
            // 查询订单
            $response = $api->get($url, $data);
            $result   = $response->toArray();
        } elseif ($transaction_id) {
            // 微信支付订单号查询订单
            $url = "v3/pay/transactions/id/{$transaction_id}";
            // 查询订单
            $response = $api->get($url, $data);
            $result   = $response->toArray();
        } else {
            $result = [];
        }
        return $result;
    }

    /**
     * 微信退款通知
     *
     */
    public function refund_notify()
    {
        trace('这是一条退款回调日志信息', 'notice');
        // 创建微信小程序对象
        $app    = \app\common\service\EasyWechatService::getPayApp();
        $server = $app->getServer();
        $server->handleRefunded(function (\app\common\service\Message $message, \Closure $next)
        {
            trace($message, 'notice');
            // $message->out_trade_no 获取商户订单号
            // $message->payer['openid'] 获取支付者 openid
            return $next($message);
        });

        // 默认返回 ['code' => 'SUCCESS', 'message' => '成功']
        return $server->serve();
    }
}